package com.anji.sp.service.impl;

import com.anji.sp.enums.UploadFileTypeEnum;
import com.anji.sp.model.ResponseModel;
import com.anji.sp.model.po.SpApplicationPO;
import com.anji.sp.model.po.SpFilePO;
import com.anji.sp.model.vo.SpUploadFileVO;
import com.anji.sp.model.vo.SpUploadVO;
import com.anji.sp.model.vo.SpVersionVO;
import com.anji.sp.service.SpApplicationService;
import com.anji.sp.service.SpFileService;
import com.anji.sp.service.SpUploadService;
import com.anji.sp.util.StringPatternUtil;
import com.anji.sp.util.StringUtils;
import com.anji.sp.util.file.FileUploadUtils;
import com.anji.sp.util.file.exception.FileException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.CacheControl;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.net.URLEncoder;
import java.util.Objects;

/**
 * @author : kean_qi
 * create at:  2020/7/1  3:37 下午
 * @description:
 */
@Service
@Slf4j
public class SpUploadServiceImpl implements SpUploadService {
    @Autowired
    SpApplicationService spApplicationService;
    @Autowired
    SpFileService spFileService;

    @Value("${customer.environment.path}")
    private String environmentFlag;
    @Value("${file.apk.url}")
    private String fileApkUrl;
    /**
     * 上传文件
     * @param spUploadVO
     * @return
     */
    @Override
    public ResponseModel uploadFile(SpUploadVO spUploadVO) {
        ResponseModel r = getUploadVO(spUploadVO);
        if (r.isError()){
            return r;
        }
        spUploadVO = (SpUploadVO) r.getRepData();
        try {
            SpUploadFileVO spUploadFileVO = FileUploadUtils.uploadFile(spUploadVO.getFile(), spUploadVO.getAppKey(), UploadFileTypeEnum.APK);
            SpVersionVO spVersionVO = new SpVersionVO();
            spVersionVO.setVersionName(spUploadFileVO.getVersionName());
            spVersionVO.setVersionNumber(spUploadFileVO.getVersionNumber());
            //apk 还是原始url
            spVersionVO.setDownloadUrl(spUploadFileVO.getUrlPath());
            return ResponseModel.successData(spVersionVO);
        } catch (FileException e) {
            log.error("错误 ： {}", e);
            return ResponseModel.errorMsg(e.getArgs()[0] + "");
        } catch (Exception e) {
            return ResponseModel.errorMsg(e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseModel uploadPictureFile(SpUploadVO spUploadVO) {
        try {
            SpUploadFileVO spUploadFileVO = FileUploadUtils.uploadFile(spUploadVO.getFile(), spUploadVO.getAppKey(), UploadFileTypeEnum.PICTURE);
            SpFilePO filePO = new SpFilePO();
            filePO.setFileId(spUploadFileVO.getFileId());
            filePO.setFilePath(spUploadFileVO.getFilePath());
            filePO.setUrlPath(environmentFlag+"/sp/file/download/"+spUploadFileVO.getUrlPath());
            //插入到数据库
            ResponseModel insertResponse = spFileService.insert(filePO);
            if (insertResponse.isError()){
                return insertResponse;
            }
            return ResponseModel.successData(insertResponse.getRepData());
        } catch (FileException e) {
            log.error("错误 ： {}", e);
            return ResponseModel.errorMsg(e.getArgs()[0] + "");
        } catch (Exception e) {
            return ResponseModel.errorMsg(e.getMessage());
        }
    }

    @Override
    public ResponseEntity<byte[]> download(HttpServletRequest request, HttpServletResponse response, String fileId) {

        try {
            String userAgent = request.getHeader("User-Agent");
            //IE 特殊处理
            boolean isIEBrowser = userAgent.indexOf("MSIE") > 0;

            SpFilePO f = new SpFilePO();
            f.setFileId(fileId);
            ResponseModel re = spFileService.select(f);
            if (re.isError()){
                ResponseModel.errorMsg("文件不存在");
            }
            f = (SpFilePO) re.getRepData();
            String filePath = f.getFilePath();
            if (StringUtils.isBlank(f.getFilePath())) {
                ResponseModel.errorMsg("文件路径不存在");
            }
            String filename = filePath.substring(filePath.lastIndexOf(File.separator));
            if (StringUtils.isBlank(filename)) {
                ResponseModel.errorMsg("文件名为空");
            }
            String fileSuffix = filename.substring(filename.lastIndexOf("."));

            //根据文件后缀来判断，是显示图片\视频\音频，还是下载文件
            File file = new File(filePath);
            ResponseEntity.BodyBuilder builder = ResponseEntity.ok();
            //设置文件长度
            builder.contentLength(file.length());

            //header 塞不一样的内容
            if(StringPatternUtil.StringMatchIgnoreCase(fileSuffix, "(.png|.jpg|.jpeg|.bmp|.gif|.icon)")){
                builder.cacheControl(CacheControl.noCache()).contentType(MediaType.IMAGE_PNG);
            } else if (StringPatternUtil.StringMatchIgnoreCase(fileSuffix, "(.flv|.swf|.mkv|.avi|.rm|.rmvb|.mpeg|.mpg|.ogg|.ogv|.mov|.wmv|.mp4|.webm|.wav|.mid|.mp3|.aac)")) {
                builder.header("Content-Type", "video/mp4; charset=UTF-8");
            }else {
                //application/octet-stream 二进制数据流（最常见的文件下载）
                builder.contentType(MediaType.APPLICATION_OCTET_STREAM);
                filename = URLEncoder.encode(filename, "UTF-8");
                if (isIEBrowser) {
                    builder.header("Content-Disposition", "attachment; filename=" + filename);
                } else {
                    builder.header("Content-Disposition", "attacher; filename*=UTF-8''" + filename);
                }
            }
            return builder.body(FileUtils.readFileToByteArray(file));
        }catch (Exception e){
            log.error("error: {}", e);
            return null;
        }
    }

    private ResponseModel getUploadVO(SpUploadVO spUploadVO){
        SpApplicationPO spApplicationPO = spApplicationService.selectByAppId(spUploadVO.getAppId());
        if (Objects.isNull(spApplicationPO)) {
            return ResponseModel.errorMsg("没有该应用,无法上传");
        }
        spUploadVO.setAppKey(spApplicationPO.getAppKey());
        spUploadVO.setAppId(spApplicationPO.getAppId());
        return ResponseModel.successData(spUploadVO);
    }
}
